package com.fly.hello.web;

import java.io.IOException;
import java.util.Arrays;
import java.util.Date;

import javax.validation.Valid;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;

import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.hibernate.validator.constraints.Range;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.Resource;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;

import com.fly.core.utils.SpringContextUtils;
import com.fly.hello.web.converter.DateEditor;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.annotations.ApiOperation;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@RestController
@RequestMapping("/date")
@Api(tags = "日期转换接口")
public class DateConvertController
{
    @Autowired
    private RestTemplate restTemplate;
    
    /**
     * 方式2：@InitBinder全局日期转换
     * 
     * @param webDataBinder
     * @see [类、类#方法、类#成员]
     */
    @InitBinder
    public void dateTypeBinder(WebDataBinder webDataBinder)
    {
        // 仅支持一种格式 yyyy-MM-dd
        // webDataBinder.addCustomFormatter(new DateFormatter("yyyy-MM-dd"));
        
        // 方式3，自定义日期属性编辑器，支持多种格式 yyyy-MM-dd, yyyy-MM-dd HH:mm:ss
        webDataBinder.registerCustomEditor(Date.class, new DateEditor());
    }
    
    /**
     * 带MultipartFile post请求接口
     * 
     * @return
     * @see [类、类#方法、类#成员]
     */
    @PostMapping("/post")
    public String post(@Valid PostUser postUser)
    {
        log.info("{}", ToStringBuilder.reflectionToString(postUser.getFile()));
        return ToStringBuilder.reflectionToString(postUser, ToStringStyle.MULTI_LINE_STYLE);
    }
    
    /**
     * 带MultipartFile post请求接口
     * 
     * @return
     * @throws IOException
     * @see [类、类#方法、类#成员]
     */
    @PostMapping("/sendPost")
    @ApiOperation("前后台日期转换")
    public String sendPost(@Valid InputUser inputUser)
        throws IOException
    {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.MULTIPART_FORM_DATA);
        headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
        Resource fileAsResource = new ByteArrayResource(inputUser.getFile().getBytes())
        {
            @Override
            public String getFilename()
            {
                return inputUser.getFile().getOriginalFilename();
            }
        };
        MultiValueMap<String, Object> multipartRequest = new LinkedMultiValueMap<>();
        multipartRequest.add("file", fileAsResource);
        multipartRequest.add("name", inputUser.getName());
        multipartRequest.add("sex", inputUser.getSex());
        multipartRequest.add("age", inputUser.getAge());
        multipartRequest.add("luckDate", inputUser.getLuckDate());
        HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(multipartRequest, headers);
        String url = SpringContextUtils.getServerBaseUrl() + "/date/post";
        ResponseEntity<String> responseEntity = restTemplate.postForEntity(url, requestEntity, String.class);
        return responseEntity.getBody();
    }
}

class PostUser extends BaseUser
{
    public PostUser()
    {
        super();
    }
    
    /**
     * 方式1：@DateTimeFormat注解转换
     */
    @NotNull(message = "luckDate不能为空")
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private Date luckDate;
    
    public Date getLuckDate()
    {
        return luckDate;
    }
    
    public void setLuckDate(Date luckDate)
    {
        this.luckDate = luckDate;
    }
}

class InputUser extends BaseUser
{
    public InputUser()
    {
        super();
    }
    
    @NotBlank(message = "日期不能为空")
    @ApiModelProperty(value = "幸运日", allowableValues = "2000-01-01,2001-05-01,2003-10-01 10:02:03")
    private String luckDate;
    
    public String getLuckDate()
    {
        return luckDate;
    }
    
    public void setLuckDate(String luckDate)
    {
        this.luckDate = luckDate;
    }
}

@Data
class BaseUser
{
    @NotNull(message = "靓照不能为空")
    @ApiModelProperty(value = "靓照", required = true, position = 0)
    private MultipartFile file;
    
    @NotBlank(message = "姓名不能为空")
    @ApiModelProperty(value = "姓名", example = "小明", position = 1)
    private String name;
    
    @NotBlank(message = "性别不能为空")
    @Pattern(regexp = "F|M", message = "性别不合法")
    @ApiModelProperty(value = "性别", required = true, position = 2, example = "F", allowableValues = "F,M")
    private String sex;
    
    @NotNull(message = "年齡不能为空")
    @Min(value = 10, message = "年齡不能小于{value}")
    @Range(min = 10, max = 30, message = "年龄必须{min}-{max}")
    @ApiModelProperty(value = "年龄", example = "18", required = true, position = 3)
    private Integer age;
}
